package cn.chenxing.module.visualization.controller;

import cn.chenxing.domain.dbscan.Point;
import cn.chenxing.domain.threadlocal.ThreadData;
import cn.chenxing.domain.util.AlertUtil;
import cn.chenxing.module.visualization.service.VisualService;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXComboBox;
import de.felixroske.jfxsupport.FXMLController;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.net.URL;
import java.util.*;

/**
 * @Description DBSCAN可视化控制层
 * @Author maogen.ymg
 * @Date 2020/4/18 10:59
 */
@Lazy
@FXMLController
@Slf4j
public class VisualDbScanController implements Initializable {

    private List<Point> dbScanPointList = null;

    private WebEngine webEngine;

    @FXML
    private WebView webView;

    @FXML
    private JFXComboBox<Integer> zoomLevel;

    @FXML
    private JFXButton updateButton;

    @Autowired
    private VisualService visualService;

    DbScanData2Js apps3 = new DbScanData2Js();

    /**
     * 须公有
     */
    @Setter
    public static class DbScanData2Js {
        private String dataJson = null;
        public String getDataJson() {
            return dataJson;
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 缩放级别
        zoomLevel.getItems().addAll(18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5);
        // 获取Engine
        webEngine = webView.getEngine();
        // 获取页面路径
        String mainUrl = getClass().getResource("/html/visualDbScan.html").toExternalForm();
        // 初始化
        webEngine.load(mainUrl);
        // 设置缩放级别
        zoomLevel.setValue(12);

    }

    @FXML
    public void update() {
        if(ThreadData.get().getTrackData() == null) {
            AlertUtil.showWarnAlert("还没有数据哦", "还没导入数据，请选择文件菜单进行导入");
            return;
        }
        if(ThreadData.get().getTrackData().getDbScanResultList() == null) {
            AlertUtil.showWarnAlert("无法进行可视化", "还未进行DBSCAN聚类分析，请先分析");
            return;
        }
        // 重新加载
        webEngine.reload();
        // 传送数据
        transmitData2Js();
        updateButton.setText("更新");
    }

    /**
     * 传送数据给JS
     */
    private void transmitData2Js() {
        // 数据赋值
        dbScanPointList = ThreadData.get().getTrackData().getDbScanResultList();
        setAppsDataJson();
        webEngine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
            if (newState == Worker.State.SUCCEEDED) {
                JSObject win = (JSObject) webEngine.executeScript("window");
                // 把对象设置成为js对象
                win.setMember("apps3",apps3);
                // 设置中心点(起始点)
                win.eval(visualService.setStartPoint(ThreadData.get().getTrackData().getDbUserId()));
                // 设置缩放级别
                win.eval(visualService.setZoomLevel(zoomLevel.getValue()));
                // 设置簇值
                win.eval(setClusterNum(dbScanPointList.get(dbScanPointList.size()-1).getCluster() + 1));
                // 执行操作
                webEngine.executeScript("execute()");
            }
        });
    }

    /**
     * 设置Apps的数据Json
     */
    private void setAppsDataJson() {
        if (dbScanPointList == null) {
            AlertUtil.showErrorAlert("数据读取失败", "DBSCAN分析结果数据读取失败，请检查！");
            return;
        }

        StringBuilder sb = new StringBuilder();

        // 按照cluster进行排序----点图不需要顺序！！
        dbScanPointList.sort(Comparator.comparingLong(Point::getCluster));
        // 第一个值
        int cluster = dbScanPointList.get(0).getCluster();
        // start
        sb.append("[[");
        //样例：[[[112.11888, 32.6726],[112.0409, 32.7434]],[[112.2000, 32.60335],[112.1169, 32.5076]]]
        for(Point point : dbScanPointList) {
            if(point.getCluster() != cluster) {
                // 去掉多余一个逗号
                sb.deleteCharAt(sb.length()-1);
                sb.append("],[");
                cluster++;
            }
            sb.append("[").append(point.getX()).append(",").append(point.getY()).append("],");
        }
        // end
        sb.deleteCharAt(sb.length()-1);
        sb.append("]]");

        apps3.setDataJson(sb.toString());
    }

    /**
     * 设置簇个数
     * @param cluster 簇
     * @return 方法名
     */
    private String setClusterNum(int cluster) {
        return "setClusterNum(" + cluster + ")";
    }

}